package com.suray.wcs.service.thread.process;

import com.suray.basic.wcs.plc.enums.*;
import com.suray.basic.wcs.plc.pojo.oper.single.DeviceInterface;
import com.suray.basic.wcs.plc.pojo.oper.single.MonomerConveyorOper;
import com.suray.basic.wcs.plc.pojo.oper.single.TransPlanter;
import com.suray.basic.wcs.utils.LoggerUtil;
import com.suray.commin.core.utils.SpringContextHolder;
import com.suray.wcs.service.system.entity.TaskDB;
import com.suray.wcs.service.system.service.impl.NodeDBServiceImpl;
import com.suray.wcs.service.thread.process.util.SingleDeviceProType;
import com.suray.wcs.service.util.WcsUtil;

import java.io.IOException;

/**
 * 移栽机流程
 */
public class TransPlanterProcess extends SingelDeviceProcess {
    private NodeDBServiceImpl nodeDBService = SpringContextHolder.getBean(NodeDBServiceImpl.class);

    /**
     * 流程类型
     */
    private SingleDeviceProType proType;

    private TransPlanter startTransPlanter;

    private TransPlanter endTransPlanter;

    private MonomerConveyorOper startConvery;

    private MonomerConveyorOper endConvery;

    /**
     * 单体设备流程
     *
     * @param startDevice        : 起点设备
     * @param endDevice          : 终点设备
     * @param taskDB             : 任务
     */
    public TransPlanterProcess(DeviceInterface startDevice, DeviceInterface endDevice, TaskDB taskDB) {
        super(startDevice, endDevice, taskDB, true, true, false,
                false, 60);

        if (startDevice.getPlcDeviceType() == PlcDeviceType.TRANS_PLANTER
                && endDevice.getPlcDeviceType() == PlcDeviceType.TRANS_PLANTER) {
            proType = SingleDeviceProType.移栽至移栽;
            startTransPlanter = (TransPlanter) startDevice;
            endTransPlanter = (TransPlanter) endDevice;
        } else if (startDevice.getPlcDeviceType() == PlcDeviceType.TRANS_PLANTER
                && endDevice.getPlcDeviceType() == PlcDeviceType.MONOMER_CONVEYOR) {
            proType = SingleDeviceProType.移栽至输送;
            startTransPlanter = (TransPlanter) startDevice;
            endConvery = (MonomerConveyorOper) endDevice;
        } else if (startDevice.getPlcDeviceType() == PlcDeviceType.MONOMER_CONVEYOR
                && endDevice.getPlcDeviceType() == PlcDeviceType.TRANS_PLANTER) {
            proType = SingleDeviceProType.输送至移栽;
            startConvery = (MonomerConveyorOper) startDevice;
            endTransPlanter = (TransPlanter) endDevice;
        } else {
            throw new RuntimeException("起点设备类型为：" + startDevice.getPlcDeviceType() + ", 终点设备类型为:"
                    + endDevice.getPlcDeviceType() + ", 不能执行移栽机流程");
        }
    }

    @Override
    protected boolean waitDevicePermitRun() {
        boolean endHasCargo = WcsUtil.isNodeHasCargo(endDevice.getCoord(), nodeDBService);
        switch (proType) {
            case 移栽至移栽:
            case 移栽至输送:
                LoggerUtil.info(startDevice.getDeviceName() + "允许运行？" + startDevice.permitRun() + ", " +
                                endDevice.getDeviceName() + "允许运行？" + endDevice.permitRun() +
                                ", 终点无货?" + !(endDevice.hasCargo() || endHasCargo) + ", 起点有货?" + startDevice.hasCargo(),
                        this.getClass());
                if (startDevice.permitRun() && endDevice.permitRun() && !endDevice.hasCargo() && !endHasCargo
                        && startDevice.hasCargo()) {
                    return true;
                }
                break;
            case 输送至移栽:
                LoggerUtil.info(startDevice.getDeviceName() + "允许运行？" + startDevice.canControl() + ", " +
                                endDevice.getDeviceName() + "允许运行？" + endDevice.permitRun() +
                                ", 终点无货?" + !(endDevice.hasCargo() || endHasCargo) + ", 起点有货?" + startDevice.hasCargo(),
                        this.getClass());
                if (startDevice.canControl() && endDevice.permitRun() && !endDevice.hasCargo() && !endHasCargo
                        && startDevice.hasCargo()) {
                    return true;
                }
            default:
                break;
        }

        return false;
    }

    @Override
    protected boolean startDevicePreAction() throws IOException {
        switch (proType) {
            case 移栽至移栽:
            case 移栽至输送:
                transPlanterLift(startTransPlanter, endDevice.getLocation());
                break;
            default:
                break;
        }

        return true;
    }

    /**
     * 移栽机升降
     * @param transPlanter
     * @param location
     */
    private void transPlanterLift(TransPlanter transPlanter, Location location) throws IOException {
        if (location == Location.UP) {
            //移栽机顶升
            if (!transPlanter.isRiseInPlace()) {
                transPlanter.platformRise();
            }
        } else if (location == Location.DOWN) {
            //移栽机下降
            if (!transPlanter.isDropInPlace()) {
                transPlanter.platformDrop();
            }
        } else {
            throw new RuntimeException("Location错误，移栽无法升降：" + location);
        }
    }

    @Override
    protected boolean endDevicePreAction() throws IOException {
        switch (proType) {
            case 移栽至移栽:
            case 输送至移栽:
                if (startDevice.getLocation() == null) {
                    throw new RuntimeException("设备位置为空，移栽无法动作:" + startDevice);
                }
                transPlanterLift(endTransPlanter, startDevice.getLocation());
                break;
            default:
                break;
        }

        return true;
    }

    @Override
    protected boolean waitDevicePreActionEnd() {
        switch (proType) {
            case 移栽至移栽:
                if (isTransPlanterArrive(startTransPlanter, endDevice)
                        || isTransPlanterArrive(endTransPlanter, startDevice)) {
                    return true;
                }
                break;
            case 移栽至输送:
                if (isTransPlanterArrive(startTransPlanter, endDevice)) {
                    return true;
                }
                break;
            case 输送至移栽:
                if (startDevice.getLocation() == Location.UP && endTransPlanter.isRiseInPlace()) {
                    return true;
                } else if (startDevice.getLocation() == Location.DOWN && endTransPlanter.isDropInPlace()) {
                    return true;
                }
                break;
            default:
                break;
        }

        return false;
    }

    private boolean isTransPlanterArrive(TransPlanter transPlanter, DeviceInterface device) {
        if (device.getLocation() == Location.UP && !transPlanter.isRiseInPlace()) {
            LoggerUtil.debug("等待" + transPlanter.getDeviceName() + " 上升到位", this.getClass());
            return false;
        } else if (device.getLocation() == Location.DOWN && !transPlanter.isDropInPlace()) {
            LoggerUtil.debug("等待" + transPlanter.getDeviceName() + " 下降到位", this.getClass());
            return false;
        }

        return true;
    }

    @Override
    protected boolean endDeviceInCargo() throws IOException {
        switch (proType) {
            case 移栽至移栽:
            case 输送至移栽:
                if (taskIn) {
                    endTransPlanter.platformForwardOut();
                } else {
                    endTransPlanter.platformReverseOut();
                }
                break;
            case 移栽至输送:
                if (taskIn) {
                    endConvery.converyRun(SingleConveryRunType.CONVERY, Direction.IN, ConveryTaskType.OUT);
                } else {
                    endConvery.converyRun(SingleConveryRunType.CONVERY, Direction.OUT, ConveryTaskType.OUT);
                }
                break;
            default:
                break;
        }

        return true;
    }

    @Override
    protected boolean startDeviceOutCargo() throws IOException {
        switch (proType) {
            case 移栽至移栽:
            case 移栽至输送:
                if (taskIn) {
                    endConvery.converyRun(SingleConveryRunType.CONVERY, Direction.IN, ConveryTaskType.IN);
                } else {
                    endConvery.converyRun(SingleConveryRunType.CONVERY, Direction.OUT, ConveryTaskType.IN);
                }
                break;
            case 输送至移栽:
                if (taskIn) {
                    endTransPlanter.platformForwardIn();
                } else {
                    endTransPlanter.platformReverseIn();
                }
                break;
            default:
                break;
        }

        return true;
    }

    @Override
    protected boolean waitDeviceRunEnd() {
        switch (proType) {
            case 移栽至移栽:
            case 输送至移栽:
                if (startDevice.hasCargo()) {
                    startDevice.setDeviceStatus("等待货物离开");
                    break;
                } else {
                    startDevice.setDeviceStatus("");
                }
                if (taskIn) {
                    if (!endTransPlanter.isInCargoSignalValid()) {
                        endDevice.setDeviceStatus("等待入库光电有信号");
                        break;
                    }
                } else {
                    if (!endTransPlanter.isOutCargoSignalValid()) {
                        endDevice.setDeviceStatus("等待出库光电有信号");
                        break;
                    }
                }
                if (endDevice.isRunning()) {
                    endDevice.setDeviceStatus("等待停止运行");
                    break;
                }

                endDevice.setDeviceStatus("");
                return true;
            case 移栽至输送:
                if (startDevice.hasCargo()) {
                    startDevice.setDeviceStatus("等待货物离开");
                    break;
                } else {
                    startDevice.setDeviceStatus("");
                }

                if (!endDevice.hasCargo()) {
                    endDevice.setDeviceStatus("等待货物到达");
                }

                endDevice.setDeviceStatus("");
                return true;
            default:
                break;
        }

        return false;
    }

    @Override
    protected boolean startDeviceAftAction() {
        return false;
    }

    @Override
    protected boolean endDeviceAftAction() {
        return false;
    }

    @Override
    protected boolean waitDeviceAftActionEnd() {
        return false;
    }
}
